/*
 * ExtentSort.cpp
 *
 *  Created on: Dec 18, 2011
 *      Author: Gal
 */

#include "ExtentSort.h"
#include <iostream>
#include <map>
#include <string>
using namespace std;

map<Extent, ExtentSumStatistics*> exMap;
ExtentSumStatistics* b[2840];	// should be the map's size


ExtentSort::ExtentSort(){
	
}

ExtentSort::~ExtentSort(){
	map<Extent, ExtentSumStatistics*> Map;
	map<Extent, ExtentSumStatistics*>::iterator Iter;
	Iter=Map.begin();
	while(Iter!=Map.end()){
		delete (*Iter).second;
		Iter++;
	}
}

void ExtentSort::create(SystemView* sys){
	ExtentEntry* e;
	bool found=false;
	bool keep;

	min =(sys->getTotal_time()/2);
	exMap=map<Extent, ExtentSumStatistics*>();
	map<Extent,ExtentSumStatistics*>::iterator ExtentIterator;
	set<ExtentEntry*>::iterator entriesIterator;
	set<ExtentEntry*>* s = sys->getMy_entries();
	int dup=0, newE=0;
	for(entriesIterator =s->begin(); entriesIterator != s->end(); entriesIterator++)
	{
		if((*entriesIterator)->getMy_time()<min){
			Extent ex = *(((ExtentEntry*)(*entriesIterator))->my_extent);
			ExtentStatistics* exStats = ((ExtentEntry*)(*entriesIterator))->my_stat;		// stats to be added
			//cout<<exStats.statistics[rand_rm]<<" ";
			ExtentSumStatistics* total;
			ExtentIterator = exMap.find(ex);
			if (ExtentIterator!=exMap.end()){		//extent exist already
				dup++;
				total = exMap.at(ex);// get extent total statistics
				ExtentStatistics* extentStats = (total->my_stats);
				//extentStats->statistics[0]=extentStats->statistics[0]+exStats.statistics[0];
				extentStats->addStatistics(exStats);
				//for (int k=0; k<11;k++)
					//cout<<total->my_stats.statistics[rand_rm]<<" ";
			}
			else{
				if ((exMap.find(ex))!=exMap.end())
					cout<<"here************************************************"<<endl;
				newE++;
				ExtentSumStatistics* es = new ExtentSumStatistics(ex.my_lunID, ex.my_offset, ex.lunPriority, exStats);				
				exMap.insert(pair<Extent, ExtentSumStatistics*>(ex, es));
				//cout<<es.my_stats.statistics[rand_rm]<<" ";
			}
		}
	}

	// move map to array
	cout<<"map size: "<<exMap.size()<<endl;
	//ExtentSumStatistics arr[3180];		//****************** should be the map size
	map<Extent, ExtentSumStatistics*>::iterator mapIter;
	int i=0;
	for (mapIter=exMap.begin(); mapIter!=exMap.end(); mapIter++, i++)
		sortedExtents[i]=mapIter->second;
	
	merge_sort(0, 2839);

}


void ExtentSort::merge_sort(int low,int high)
{
	//cout<<"in merge sort"<<endl;
	int mid;
	if(low<high)
	{
		mid=(low+high)/2;
		merge_sort(low,mid);
		merge_sort(mid+1,high);
		merge(low,mid,high);
	}
}

void ExtentSort::merge(int low,int mid,int high)
{
	int h,i,j,k;
	h=low;
	i=low;
	j=mid+1;

	while((h<=mid)&&(j<=high))
	{
		if(sortedExtents[h]->my_stats->statistics[rand_rm]>=10)//sortedExtents[j]->my_stats->statistics[rand_rm])
		{
			b[i]=sortedExtents[h];
			h++;
		}
		else
		{
			b[i]=sortedExtents[j];
			j++;
		}
		i++;
	}
	if(h>mid)
	{
		for(k=j;k<=high;k++)
		{
		b[i]=sortedExtents[k];
		i++;
		}
	}
	else
	{
		for(k=h;k<=mid;k++)
		{
		b[i]=sortedExtents[k];
		i++;
		}
	}
	for(k=low;k<=high;k++) sortedExtents[k]=b[k];
}


// returns for each drive (SSD,FC,SATA) how many random read miss where in it during the second part of the day
map<string, int> ExtentSort::compare(SystemView* sys){
	int count=0;
	
	map<string, int> ans;
	ans.insert(pair<string, int>("SSD", 0));
	ans.insert(pair<string, int>("FC", 0));
	ans.insert(pair<string, int>("SATA", 0));

	bool stop=false;
	int size = 3000;	//**************************************************
	ExtentEntry* e;
	ExtentSumStatistics* es;
	map<string, int>::iterator iter;
	set<ExtentEntry*>::iterator entriesIterator;
	set<ExtentEntry*>* s = sys->getMy_entries();
	entriesIterator =s->begin();
	while(entriesIterator != s->end()){
		
		stop=false;
		e = (*entriesIterator);		// extent entry
		if (e->my_time>min){
			count+=e->my_stat->statistics[rand_rm];
			set<ExtentSumStatistics*>::iterator extentIterator;
			//for(extentIterator =extents.begin(); (extentIterator != extents.end()) & !stop; extentIterator++){
			for (int k=0; k<2840; k++){		// should be exMap's size
				es=sortedExtents[k];
				if (e->my_extent->operatorEqual(*es->my_extent)){
					stop=true;
					if (k<=(0.1*size)){
						iter=ans.find("SSD");
						count++;
						//cout<<es.my_stats.statistics[rand_rm]<<" ";
						iter->second+=e->my_stat->statistics[rand_rm];
					}
					else if (k<=(0.3*size)){
						iter=ans.find("FC");
						iter->second+=e->my_stat->statistics[rand_rm];
					}
					else{
						iter=ans.find("SATA");
						if ((e->my_stat->statistics[rand_rm])>0)
						//cout<<"SATA: "<<e->my_stat->statistics[rand_rm];
						iter->second+=e->my_stat->statistics[rand_rm];
					}
				}
			}
		}
		entriesIterator++;
	}
	//cout<<"count "<<count<<endl;
	return ans;
}

